From 17d82d88cf6c35aa507d79afaf58dbda2b8aa833 Mon Sep 17 00:00:00 2001 From: robertl Date: Tue, 9 Nov 2004 17:56:59 +0000 Subject: [PATCH] Add Coastal Explorer courtesy justinbr of earthlink.net. (Yes, it leaks...) --- gpsbabel/Makefile | 2 +- gpsbabel/README | 7 + gpsbabel/coastexp.c | 421 ++++++++++++++++++++++++++++++++ gpsbabel/reference/coastexp.nob | 370 ++++++++++++++++++++++++++++ gpsbabel/reference/coastexp.ref | 180 ++++++++++++++ gpsbabel/testo | 6 + gpsbabel/vecs.c | 7 + 7 files changed, 992 insertions(+), 1 deletion(-) create mode 100755 gpsbabel/coastexp.c create mode 100755 gpsbabel/reference/coastexp.nob create mode 100755 gpsbabel/reference/coastexp.ref diff --git a/gpsbabel/Makefile b/gpsbabel/Makefile index 22016bbec..970258f55 100644 --- a/gpsbabel/Makefile +++ b/gpsbabel/Makefile @@ -25,7 +25,7 @@ FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o garmin_tables.o \ xcsv.o gcdb.o tiger.o internal_styles.o easygps.o quovadis.o \ gpilots.o saroute.o navicache.o psitrex.o geoniche.o delgpl.o \ ozi.o nmea.o text.o html.o palmdoc.o netstumbler.o hsa_ndv.o \ - igc.o brauniger_iq.o shape.o hiketech.o glogbook.o + igc.o brauniger_iq.o shape.o hiketech.o glogbook.o coastexp.o FILTERS=position.o duplicate.o arcdist.o polygon.o smplrout.o reverse_route.o sort.o stackfilter.o diff --git a/gpsbabel/README b/gpsbabel/README index dd1dead27..fb6bf5894 100644 --- a/gpsbabel/README +++ b/gpsbabel/README @@ -473,6 +473,13 @@ THE FORMATS http://www.navicache.com/cgi-bin/ib312a/ikonboard.cgi?act=ST;f=23;t=334 + coastexp + + This is the XML format used by CoastalExplorer (tm). For the moment + this is only available as an input format. + + http://www.rosepointnav.com + PsiTrex This is a text format created by KuDaTa's PsiTrex program for the Psion diff --git a/gpsbabel/coastexp.c b/gpsbabel/coastexp.c new file mode 100755 index 000000000..b8e19ecdc --- /dev/null +++ b/gpsbabel/coastexp.c @@ -0,0 +1,421 @@ +/* + Copyright (C) 2004 Justin Broughton, justinbr@earthlink.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ + +#include "defs.h" +#if !NO_EXPAT +#include +static XML_Parser psr; +#endif + +FILE *fd; +FILE *ofd; + +#define MYNAME "coastexp" +#define MY_CBUF 4096 + +#if NO_EXPAT +void +ce_rd_init(const char *fname) +{ + fatal(MYNAME ": This build excluded CoastalExplorer support because expat was not installed.\n"); +} + +void +ce_read(void) +{ +} +#else + +static char *element; // Current element being parsed +static char *cdatastr; // Current XML character data being built up (until a ) + +/* CE-specific mark structure - used for both route marks and standalone marks */ +struct CE_MARK { + struct CE_MARK *next; // pointer to next mark in list + char *id; // CE's mark ID (of the form "{}") + waypoint *wp; // GPSBabel waypoint + int used; // Is this mark used in a route or not? +}; +typedef struct CE_MARK ce_mark; + +/* CE-specific route structure */ +struct CE_ROUTE { + struct CE_ROUTE *next; // pointer to next route in list + char *id; // CE's route ID (of the form "{}") + route_head *r; // GPSBabel route header + ce_mark *marks; // list of CE marks in this route +}; +typedef struct CE_ROUTE ce_route; + +static ce_route *routes = NULL; // List of routes currently found +static ce_route *currentRoute = NULL; // Current route being processed +static ce_mark *marks = NULL; // List of stand-alone marks currently found +static ce_mark *currentMark = NULL; // Current mark being processed +static int inRoute = 0; // Are we processing a route? +static int inMark = 0; // Are we processing a mark? + +/* Add a route to the list of routes */ +static void +add_route(ce_route *route) +{ + if (routes == NULL) { + routes = route; + } else { + ce_route *curr = routes; + while (curr->next != NULL) + curr = curr->next; + curr->next = route; + } +} + +/* Add a mark to the list of stand-alone marks */ +static void +add_mark(ce_mark *mark) +{ + if (marks == NULL) { + marks = mark; + } else { + ce_mark *curr = marks; + while (curr->next != NULL) + curr = curr->next; + curr->next = mark; + } +} + +/* Add a mark to the specified route */ +static void +add_mark_to_route(ce_route *route, ce_mark *mark) +{ + if (route->marks == NULL) { + route->marks = mark; + } else { + ce_mark *curr = route->marks; + while (curr->next != NULL) + curr = curr->next; + curr->next = mark; + } +} + +/* Start processing an XML item */ +static void +ce_start(void *data, const char *el, const char **attr) +{ + element = xstrdup(el); + if (0 == strcmp(el, "Route")) { + inRoute = 1; + const char **ap; + for (ap = attr; *ap; ap+=2) { + if (0 == strcmp(ap[0], "id")) { + // Create a CE route object and add it to the list of routes + currentRoute = (ce_route *) xcalloc(sizeof (ce_route), 1); + currentRoute->next = NULL; + currentRoute->id=xstrdup(ap[1]); + currentRoute->r = route_head_alloc(); + currentRoute->marks = NULL; + add_route(currentRoute); + } + } + } else if (0 == strcmp(el, "Mark")) { + inMark = 1; + const char **ap; + for (ap = attr; *ap; ap+=2) { + if (0 == strcmp(ap[0], "id")) { + // Create a CE mark object and add it to the list of stand-alone marks + currentMark = (ce_mark *) xcalloc(sizeof (ce_mark), 1); + currentMark->next = NULL; + currentMark->id=xstrdup(ap[1]); + currentMark->wp = NULL; + currentMark->used = 0; + add_mark(currentMark); + } + } + } +} + +/* Finish processing an XML item */ +static void +ce_end(void *data, const char *el) +{ + if (0 == strcmp(el, "Route")) + inRoute = 0; + else if (0 == strcmp(el, "Mark")) + inMark = 0; +} + +/* Process some XML character data for the current item */ +static void +ce_cdata(void *dta, const XML_Char *s, int len) +{ + if (*s != '\n') { + // We buffer up characters in 'cdatastr' until a single is received + if ((strlen(cdatastr) + len) > MY_CBUF) { + printf("Buffer overflow - line too long!"); + exit(-1); + } + char *edatastr = cdatastr+strlen(cdatastr); + memcpy(edatastr, s, len); + edatastr[len] = '\0'; + } else { + // Now process what we have in 'cdatastr' + s = cdatastr; + while (*s != '\0' && (*s == '\b' || *s == '\t')) + s++; + if (strlen(s) <= 0) + return; + if (0 == strcmp(element, "Marks")) { + if (inRoute == 1) { + // We are processing the marks in a route so create a CE mark object + // and add it to the current route + ce_mark *mark = (ce_mark *) xcalloc(sizeof (ce_mark), 1); + mark->next = NULL; + mark->id = xstrdup(s); + mark->wp = NULL; + add_mark_to_route(currentRoute, mark); + } + } else if (0 == strcmp(element, "Position")) { + if (inMark == 1) { + // We are processing a standalone mark so read the lat/long position + // and create a waypoint to add to the current mark + char *position = xstrdup(s); + char *lat = position; + char *latNorS = position; + while (*latNorS != ' ') + latNorS++; + *latNorS++ = '\0'; + char *lng = latNorS; + lng++; lng++; + char *longEorW = lng; + while (*longEorW != ' ') + longEorW++; + *longEorW++ = '\0'; + currentMark->wp = waypt_new(); + currentMark->wp->latitude = atof(lat); + if (*latNorS == 'S') + currentMark->wp->latitude = -currentMark->wp->latitude; + currentMark->wp->longitude = atof(lng); + if (*longEorW == 'W') + currentMark->wp->longitude = -currentMark->wp->longitude; + } + } else if (0 == strcmp(element, "Name")) { + // Names we care about may be either for routes or marks + char *name = xstrdup(s); + if (inMark == 1) + currentMark->wp->shortname = name; + else if (inRoute == 1) + currentRoute->r->rte_name = name; + } else if (0 == strcmp(element, "Description")) { + // Descriptions we care about may be either for routes or marks + char *desc = xstrdup(s); + if (inMark == 1) + currentMark->wp->description = desc; + else if (inRoute == 1) + currentRoute->r->rte_desc = desc; + } + + // Start building a new string since we are done with this one + cdatastr[0] = '\0'; + } +} + +/* Set up reading the CE input file */ +void +ce_rd_init(const char *fname) +{ + fd = xfopen(fname, "r", MYNAME); + + psr = XML_ParserCreate(NULL); + if (!psr) { + fatal(MYNAME ":Cannot create XML parser\n"); + } + + XML_SetElementHandler(psr, ce_start, ce_end); + cdatastr = xcalloc(MY_CBUF,1); + XML_SetCharacterDataHandler(psr, ce_cdata); +} + +/* Parse the input file */ +void +ce_read(void) +{ + int len; + char buf[MY_CBUF]; + + while ((len = fread(buf, 1, sizeof(buf), fd))) { + if (!XML_Parse(psr, buf, len, feof(fd))) { + fatal(MYNAME ":Parse error at %d: %s\n", + XML_GetCurrentLineNumber(psr), + XML_ErrorString(XML_GetErrorCode(psr))); + } + } + + XML_ParserFree(psr); +} + +#endif + +/* Fix waypoints in route marks from the standalone marks */ +void +ce_fix_waypoints(void) +{ + ce_route *route = routes; + while (route != NULL) { + ce_mark *mark = route->marks; + while (mark != NULL) { + ce_mark *mark2 = marks; + while (mark2 != NULL) { + if (0 == strcmp(mark->id, mark2->id)) { + mark->wp = mark2->wp; + mark2->used = 1; + break; + } + mark2 = mark2->next; + } + mark = mark->next; + } + route = route->next; + } +} + +/* Check route name and if NULL assign a name */ +void +ce_check_route_names(void) +{ + ce_route *route = routes; + while (route != NULL) { + if (route->r->rte_name == NULL) { + cdatastr = '\0'; + strcat(cdatastr, marks->wp->shortname); + strcat(cdatastr, "->"); + ce_mark *mark = route->marks; + while (mark->next != NULL) + mark = mark->next; + strcat(cdatastr, mark->wp->shortname); + route->r->rte_name = xstrdup(cdatastr); + } + route = route->next; + } +} + +/* Remove marks used in routes */ +void +ce_remove_unused_marks(void) +{ + ce_mark *mark = marks; + ce_mark *prev_mark = NULL; + while (mark != NULL) { + if (mark->used == 1) { + if (prev_mark == NULL) + marks = mark = mark->next; + else + prev_mark->next = mark = mark->next; + continue; + } + prev_mark = mark; + mark = mark->next; + } +} + +/* Print out results */ +void +ce_print_results(void) +{ + ce_route *curr_route = routes; + while (curr_route != NULL) { + printf("Route name=%s id=%s\n", curr_route->r->rte_name, curr_route->id); + ce_mark *curr_mark = curr_route->marks; + while (curr_mark != NULL) { + if (curr_mark->wp == NULL) + printf(" null\n"); + else + printf(" %s (%f, %f)\n", curr_mark->wp->shortname, curr_mark->wp->latitude, curr_mark->wp->longitude); + curr_mark = curr_mark->next; + } + curr_route = curr_route->next; + } + ce_mark *curr_mark = marks; + while (curr_mark != NULL) { + printf("Mark name=%s id=%s ", curr_mark->wp->shortname, curr_mark->id); + if (curr_mark->wp == NULL) + printf("(null)\n"); + else + printf("(%f, %f)\n", curr_mark->wp->latitude, curr_mark->wp->longitude); + curr_mark = curr_mark->next; + } +} + +/* Finish reading the input file */ +void +ce_rd_deinit(void) +{ + ce_fix_waypoints(); + ce_check_route_names(); + ce_remove_unused_marks(); + // ce_print_results(); + + // Add routes to GPSBabel + ce_route *route = routes; + while (route != NULL) { + route_add_head(route->r); + ce_mark *mark = route->marks; + while (mark->next != NULL) { + route_add_wpt(route->r, mark->wp); + mark = mark->next; + } + route = route->next; + } + + // Add (unused) marks to GPSBabel + ce_mark *mark = marks; + while (mark != NULL) { + waypt_add(mark->wp); + mark = mark->next; + } + + fclose(fd); +} + +void +ce_wr_init(const char *fname) +{ + fatal(MYNAME ": Does not support writing CoastalExplorer files.\n"); + ofd = xfopen(fname, "w", MYNAME); +} + +void +ce_wr_deinit(void) +{ + fclose(ofd); +} + +void +ce_write(void) +{ +} + +ff_vecs_t coastexp_vecs = { + ff_type_file, + ce_rd_init, + ce_wr_init, + ce_rd_deinit, + ce_wr_deinit, + ce_read, + ce_write, + NULL, + NULL, +}; diff --git a/gpsbabel/reference/coastexp.nob b/gpsbabel/reference/coastexp.nob new file mode 100755 index 000000000..899175639 --- /dev/null +++ b/gpsbabel/reference/coastexp.nob @@ -0,0 +1,370 @@ + + + Navigation Objects + true + + 34.867273 N 120.589158 W + 98208.414698 + true + true + + + + {76e5356a-d5fc-4437-8649-026416c2b185} + {d5dbd16f-eeba-4f61-b38f-582b584e5db3} + {9816402a-51a6-4fd5-8c08-b680d23d7911} + {427ed2ff-bdbb-4d77-b859-1f1eff10c961} + {0ead9569-64f0-4fb8-9545-4fa3191bbab0} + {fbe5b26d-b111-4208-ac70-f22b169d9c3e} + {68cfe23d-2ebf-4075-9726-f743659c7df5} + {50740d73-e743-4197-a6a0-29ad3114107a} + {26ae0ba0-a73e-4600-b51a-546d7099c809} + {b7266cd5-817b-4674-862e-490230a2f925} + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + + 5.0 kn + + true + 39.06 NM + 20050516T070000 + first-waypoint + Into The Bay + + + 37.763290 N 122.282580 W + Home + 0.05 NM + 0 NM + -51,-21 + 0,24 + SFBALBAY + + + 37.751613 N 122.339028 W + 0.05 NM + 0 NM + -58,4 + 0,24 + SFBAY001 + + + 37.817420 N 122.394305 W + 0.05 NM + 0 NM + -9,-19 + 0,24 + SFBAY002 + + + 37.819339 N 122.478302 W + 0.05 NM + 0 NM + -53,-21 + 0,24 + SFGGBRDG + + + 37.773033 N 122.605838 W + 0.05 NM + 0 NM + -92,-13 + 0,24 + SFCHNL01 + + + 37.518860 N 122.529914 W + 0.05 NM + 0 NM + -98,-4 + 0,24 + HMCOLREF + + + 37.482348 N 122.507704 W + 0.05 NM + 0 NM + -77,1 + 0,24 + HMPILL01 + + + 37.476448 N 122.475800 W + 0.05 NM + 0 NM + 13,-1 + 0,24 + HMPILL02 + + + 37.495102 N 122.483927 W + 0.05 NM + 0 NM + -91,-4 + 0,24 + HMPILL03 + + + 37.229349 N 122.441589 W + 0.05 NM + 0 NM + -95,-4 + 0,24 + PESCDR01 + + + 37.183397 N 122.411904 W + 0.05 NM + 0 NM + -90,-2 + 0,24 + PIGEON01 + + + 37.090736 N 122.348775 W + 0.05 NM + 0 NM + -89,0 + 0,24 + ANONUV01 + + + 36.929502 N 122.113725 W + 0.05 NM + 0 NM + -51,4 + 0,24 + SCRUZ01 + + + 36.934235 N 122.022130 W + 0.05 NM + 0 NM + 22,-8 + 0,24 + SCRUZ02 + + + 36.960666 N 122.024734 W + 0.05 NM + 0 NM + 22,-9 + 0,24 + SCRUZENT + + + 37.475062 N 122.488531 W + 0.05 NM + 0 NM + -44,5 + 0,24 + HMPILLPT + + + 36.581344 N 121.995411 W + 0.05 NM + 0 NM + -95,-7 + 0,24 + CYPRSSPT + + + 36.301110 N 121.919097 W + 0.05 NM + 0 NM + -67,-3 + 0,24 + PTSUR + + + 36.238177 N 121.855209 W + 0.05 NM + 0 NM + -72,3 + 0,24 + COOPERPT + + + 36.225175 N 121.801314 W + 0.05 NM + 0 NM + -91,-8 + 0,24 + PFEIFENT + + + 36.230449 N 121.797444 W + Anchor + 0.05 NM + 0 NM + -85,-14 + 0,24 + PFEIFANC + + + 35.879801 N 121.498947 W + 0.05 NM + 0 NM + 10,-15 + 0,24 + SANMRT01 + + + 35.652801 N 121.308485 W + 0.05 NM + 0 NM + -75,2 + 0,24 + PDRSBLNC + + + 35.623297 N 121.185920 W + 0.05 NM + 0 NM + -102,-6 + 0,24 + SNSMNENT + + + 35.640478 N 121.183772 W + Anchor + 0.05 NM + 0 NM + -105,-9 + 0,24 + SNSMNANC + + + 35.572353 N 121.152797 W + 0.05 NM + 0 NM + -80,-1 + 0,24 + CAMBRIA + + + 35.449214 N 121.020825 W + 0.05 NM + 0 NM + 14,-14 + 0,24 + PTESTERO + + + 35.216602 N 120.928391 W + 0.05 NM + 0 NM + -96,-3 + 0,24 + PTBUCHON + + + 34.883361 N 120.684631 W + 0.05 NM + 0 NM + -57,3 + 0,24 + PTSAL01 + + + 34.884641 N 120.652026 W + 0.05 NM + 0 NM + -96,-8 + 0,24 + PTSALENT + A description of the Point Sal Entrance mark + + + 34.896555 N 120.649124 W + Anchor + 0.05 NM + 0 NM + -96,-10 + 0,24 + PTSALANC + + + 34.758180 N 120.642516 W + 0.05 NM + 0 NM + 22,-8 + 0,24 + PURSMAPT + + + 34.572579 N 120.663636 W + 0.05 NM + 0 NM + -97,-7 + 0,24 + PTARGLLO + + + 34.113844 N 120.492630 W + 0.05 NM + 0 NM + 20,-11 + 0,24 + SANMGL01 + + + 34.029483 N 120.471409 W + 0.05 NM + 0 NM + -88,0 + 0,24 + SANMGL02 + + + 34.019184 N 120.444197 W + 0.05 NM + 0 NM + -32,5 + 0,24 + SANMGL03 + + + 34.023478 N 120.438209 W + 0.05 NM + 0 NM + 19,-4 + 0,24 + ADCOVENT + + + 34.028615 N 120.439696 W + Anchor + 0.05 NM + 0 NM + -102,-5 + 0,24 + ADCOVANC + + diff --git a/gpsbabel/reference/coastexp.ref b/gpsbabel/reference/coastexp.ref new file mode 100755 index 000000000..24568428b --- /dev/null +++ b/gpsbabel/reference/coastexp.ref @@ -0,0 +1,180 @@ + + + + + + PESCDR01 + PESCDR01 + PESCDR01 + + + PIGEON01 + PIGEON01 + PIGEON01 + + + ANONUV01 + ANONUV01 + ANONUV01 + + + SCRUZ01 + SCRUZ01 + SCRUZ01 + + + SCRUZ02 + SCRUZ02 + SCRUZ02 + + + SCRUZENT + SCRUZENT + SCRUZENT + + + CYPRSSPT + CYPRSSPT + CYPRSSPT + + + PTSUR + PTSUR + PTSUR + + + COOPERPT + COOPERPT + COOPERPT + + + PFEIFENT + PFEIFENT + PFEIFENT + + + PFEIFANC + PFEIFANC + PFEIFANC + + + SANMRT01 + SANMRT01 + SANMRT01 + + + PDRSBLNC + PDRSBLNC + PDRSBLNC + + + SNSMNENT + SNSMNENT + SNSMNENT + + + SNSMNANC + SNSMNANC + SNSMNANC + + + CAMBRIA + CAMBRIA + CAMBRIA + + + PTESTERO + PTESTERO + PTESTERO + + + PTBUCHON + PTBUCHON + PTBUCHON + + + PTSAL01 + PTSAL01 + PTSAL01 + + + PTSALENT + A description of the Point Sal Entrance mark + A description of the Point Sal Entrance mark + + + PTSALANC + PTSALANC + PTSALANC + + + PURSMAPT + PURSMAPT + PURSMAPT + + + PTARGLLO + PTARGLLO + PTARGLLO + + + SANMGL01 + SANMGL01 + SANMGL01 + + + SANMGL02 + SANMGL02 + SANMGL02 + + + SANMGL03 + SANMGL03 + SANMGL03 + + + ADCOVENT + ADCOVENT + ADCOVENT + + + ADCOVANC + ADCOVANC + ADCOVANC + + + Into The Bay + + SFBALBAY + + + SFBAY001 + + + SFBAY002 + + + SFGGBRDG + + + SFCHNL01 + + + HMCOLREF + + + HMPILL01 + + + HMPILLPT + + + HMPILL02 + + + diff --git a/gpsbabel/testo b/gpsbabel/testo index cba457c9a..82658b27c 100755 --- a/gpsbabel/testo +++ b/gpsbabel/testo @@ -401,6 +401,12 @@ ${PNAME} -i navicache -f reference/navicache.xml -o gpsutil -F ${TMPDIR}/navi.wp compare ${TMPDIR}/navi.wpt reference/navicache.ref # +# +# CoastalExplorer.. +${PNAME} -i coastexp -f reference/coastexp.nob -o gpx -F ${TMPDIR}/coastexp.gpx +compare ${TMPDIR}/coastexp.gpx reference/coastexp.ref +# + # PsiTrex. A text format that can't be handled by XCSV due to context of # data based on other data values in the file # Waypoints first diff --git a/gpsbabel/vecs.c b/gpsbabel/vecs.c index 0438d05d2..0229ebc3b 100644 --- a/gpsbabel/vecs.c +++ b/gpsbabel/vecs.c @@ -55,6 +55,7 @@ extern ff_vecs_t quovadis_vecs; extern ff_vecs_t gpilots_vecs; extern ff_vecs_t saroute_vecs; extern ff_vecs_t navicache_vecs; +extern ff_vecs_t coastexp_vecs; extern ff_vecs_t psit_vecs; /* MRCB */ extern ff_vecs_t shape_vecs; extern ff_vecs_t geoniche_vecs; @@ -224,6 +225,12 @@ vecs_t vec_list[] = { "Navicache.com XML", NULL }, + { + &coastexp_vecs, + "coastexp", + "CoastalExplorer.com XML", + NULL + }, { /* MRCB */ &psit_vecs, "psitrex", -- 2.30.2